package com.jinqing.wuchuang.utils;

import ch.qos.logback.classic.Logger;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.policy.HackLoopTableRenderPolicy;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Map;
public class WordUtil {

    private static Logger log = (Logger) LoggerFactory.getLogger(WordUtil.class);
    /**
     * 根据模板填充内容生成word，输出到本地
     * 调用方法参考下面的main方法，详细文档参考官方文档
     * Poi-tl模板引擎官方文档：http://deepoove.com/poi-tl/
     *
     * @param templatePath word模板文件路径
     * @param fileDir      生成的文件存放地址
     * @param fileName     生成的文件名,不带格式。假如要生成abc.docx，则fileName传入abc即可
     * @param paramMap     替换的参数集合
     * @return 生成word成功返回生成的文件的路径，失败返回空字符串
     */
    public static String createWordToLocal(String templatePath, String fileDir, String fileName, Map<String, Object> paramMap) {
        Assert.notNull(templatePath, "word模板文件路径不能为空");
        Assert.notNull(fileDir, "生成的文件存放地址不能为空");
        Assert.notNull(fileName, "生成的文件名不能为空");

        // 生成的word格式
        String formatSuffix = ".docx";
        // 拼接后的文件名
        fileName = fileName + formatSuffix;

        // 生成的文件的存放路径
        if (!fileDir.endsWith("/")) {
            fileDir = fileDir + File.separator;
        }

        File dir = new File(fileDir);
        if (!dir.exists()) {
            log.info("生成word数据时存储文件目录{}不存在,为您创建文件夹!", fileDir);
            dir.mkdirs();
        }

        String filePath = fileDir + fileName;

        // 动态生成表格
        HackLoopTableRenderPolicy hackLoopTableRenderPolicy = new HackLoopTableRenderPolicy();
        Configure config = Configure.newBuilder().bind("m", hackLoopTableRenderPolicy).build();
        // 读取模板templatePath并将paramMap的内容填充进模板，即编辑模板+渲染数据
        XWPFTemplate template = XWPFTemplate.compile(templatePath,config).render(paramMap);

        try {
            // 将填充之后的模板写入filePath
            template.write(new FileOutputStream(filePath));
       //     template.writeToFile(filePath);
            template.close();
        } catch (Exception e) {
            log.error("生成word异常", e);
            return "fail";
        }
        return filePath;
    }

    /**
     * 创建模板，输出到网络流
     * @param response
     * @param paramMap 填入模板的数据集
     * @return 创建结果，即成功与否
     * @throws IOException
     */
    public static String createWord(HttpServletResponse response,Map<String, Object> paramMap) throws IOException {
        XWPFTemplate template = WordUtil.getXWPFTemplate(paramMap);
        // 文件名
        String filehName = new String(("武汉理工大学大学生创新创业梦工场入驻申请表.docx").getBytes(), "ISO-8859-1");
        OutputStream out = response.getOutputStream();
        response.setCharacterEncoding("UTF-8");
//        response.setContentType("text/html;charset=utf-8");
        try {
            // 解决中文名无法显示出来的问题
            response.addHeader("Content-Disposition", "attachment;fileName=" + filehName);
            template.write(out);
        } catch (Exception e) {
            log.error("生成word异常", e);
            return "fail";
        }finally {
            out.flush();
            out.close();
            template.close();
        }
        return "success";
    }

    /**
     * 返回 multipartfile，存到文件服务器
     * @param paramMap
     * @return MultipartFile
     * @throws IOException
     */
    public static MultipartFile creatWord(Map<String, Object> paramMap) throws IOException {
        XWPFTemplate template = WordUtil.getXWPFTemplate(paramMap);
        XWPFDocument xwpfDocument = template.getXWPFDocument();
        // 文件名
        String filehName = new String(("武汉理工大学大学生创新创业梦工场入驻申请表.docx").getBytes(), "ISO-8859-1");
        MultipartFile multipartFile = WordUtil.xwpfDocumentToCommonsMultipartFile(xwpfDocument,filehName);
        return multipartFile;
    }

    /**
     * 获取 XWPFTemplate
     * @param paramMap
     * @return XWPFTemplate
     * @throws IOException
     */
    public static XWPFTemplate getXWPFTemplate(Map<String, Object> paramMap) throws IOException {
        // 即使在linux或者打jar包也不会报找不到文件的错误
        InputStream templatePath = WordUtil.class.getClassLoader().getResourceAsStream("static/doc/WordTemplate.docx");
//        String filehName = new String(("武汉理工大学大学生创新创业梦工场入驻申请表.docx").getBytes(), "UTF-8");
        // 动态生成表格
        HackLoopTableRenderPolicy hackLoopTableRenderPolicy = new HackLoopTableRenderPolicy();
        Configure config = Configure.newBuilder().bind("m", hackLoopTableRenderPolicy).build();
        // 读取模板 templatePath 并将 paramMap 的内容填充进模板，即编辑模板+渲染数据
        XWPFTemplate template = XWPFTemplate.compile(templatePath,config).render(paramMap);
        return template;

    }

    /**
     * XWPFDocument 转 MultipartFile（CommonsMultipartFile）
     *
     * @param document 文档对象
     * @param fileName 文件名
     * @return
     */
    public static MultipartFile xwpfDocumentToCommonsMultipartFile(XWPFDocument document, String fileName) {
        //XWPFDocument转FileItem
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        FileItem fileItem = factory.createItem("textField", "text/plain", true, fileName);
        try {
            OutputStream os = fileItem.getOutputStream();
            document.write(os);
            os.close();
            //FileItem转MultipartFile
            MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
            return multipartFile;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
